﻿﻿﻿﻿﻿﻿﻿using DeviceCommons.DataHandling.Compression;
using DeviceCommons.DeviceMessages.Enums;
using DeviceCommons.DeviceMessages.Models.V1;
using DeviceCommons.Security;
using DeviceCommons.Validation;

namespace DeviceCommons.DataHandling
{
    public class DeviceMessageUtilities
    {
        /// <summary>
        /// 优化的AES加密器，使用快速模式和缓存提升性能
        /// 使用ThreadLocal确保线程安全
        /// </summary>
        public static readonly ThreadLocal<AesEncryptor> AES = new ThreadLocal<AesEncryptor>(() => new AesEncryptor(true, true));
        
        /// <summary>
        /// 安全模式的AES加密器，用于生产环境
        /// 使用ThreadLocal确保线程安全
        /// </summary>
        public static readonly ThreadLocal<AesEncryptor> AES_SECURE = new ThreadLocal<AesEncryptor>(() => new AesEncryptor(false, false));
        
        public static readonly Compressor GZIP = new Compressor();
        public static void CheckBuffer(ReadOnlySpan<byte> buffer, int startIndex, int requiredLength)
        {
            ArgumentNullException.ThrowIfNull(nameof(buffer));

            if ((uint)startIndex >= (uint)buffer.Length)
                throw new ArgumentOutOfRangeException(nameof(startIndex));

            if (buffer.Length - startIndex < requiredLength)
                throw new DeviceMessageValidationException(
                    ValidationErrorType.InsufficientBufferLength,
                    "缓冲区长度不足，无法读取所需的字节数",
                    nameof(buffer),
                    $"至少需要 {requiredLength} 字节",
                    $"可用 {buffer.Length - startIndex} 字节");

            if (buffer.IsEmpty || startIndex < 0 || startIndex >= buffer.Length)
                throw new DeviceMessageValidationException(
                    ValidationErrorType.ByteArrayIndexOutOfRange,
                    "数据索引无效或数据为空",
                    nameof(startIndex),
                    "有效的索引范围",
                    startIndex);
        }

        public static int GetValueLength(StateValueTypeEnum valueType, ReadOnlySpan<byte> data, int startIndex = 0)
        {
            switch (valueType)
            {
                case StateValueTypeEnum.Float32:
                case StateValueTypeEnum.Int32:
                    return 4;
                case StateValueTypeEnum.String:
                    if (data == null || data.Length <= startIndex)
                        throw new FormatException("Invalid data format for string length field.");
                    return data[startIndex];
                case StateValueTypeEnum.Bool:
                    return 1;
                case StateValueTypeEnum.UInt16:
                case StateValueTypeEnum.Int16:
                    return 2;
                case StateValueTypeEnum.Binary:
                    if (data == null || data.Length < startIndex + 2)
                        throw new DeviceMessageValidationException(
                            ValidationErrorType.InvalidBinaryDataFormat,
                            "二进制数据长度字段读取失败，数据不完整",
                            nameof(data),
                            "至少需要2字节的长度字段",
                            $"可用数据长度: {data.Length}");
                    return BitConverter.ToUInt16(data.ToArray(), startIndex);
                case StateValueTypeEnum.Timestamp:
                    return 8;
                case StateValueTypeEnum.Double:
                    return 8;
                default:
                    throw new ArgumentOutOfRangeException(nameof(valueType), valueType, null);
            }
        }

        public static int GetValueLength(ReadOnlySpan<byte> data, int startIndex)
        {
            CheckBuffer(data, startIndex, 0);
            if (data[startIndex] > 10)
                throw new DeviceMessageValidationException(
                    ValidationErrorType.InvalidEnumValue,
                    "状态值类型枚举值超出有效范围",
                    nameof(data),
                    "StateValueTypeEnum值(0-10)",
                    data[startIndex]);


            var valueType = (StateValueTypeEnum)data[startIndex];
            switch (valueType)
            {
                case StateValueTypeEnum.String:
                    CheckBuffer(data, startIndex, 1);
                    return GetValueLength(valueType, data, startIndex + 1) + 1;
                case StateValueTypeEnum.Binary:
                    CheckBuffer(data, startIndex, 2);
                    return GetValueLength(valueType, data, startIndex + 1) + 2;
                default:
                    return GetValueLength(valueType, null);
            }
        }

        public static int GetValueLength(IDeviceMessageInfoReadingState state)
        {
            switch (state.ValueType)
            {
                case StateValueTypeEnum.String:
                    return state.Value.Length + 1;
                case StateValueTypeEnum.Binary:
                    return state.Value.Length + 2;
                default:
                    return GetValueLength(state.ValueType, null);
            }
        }
    }
}
